package utils;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
 * @author Kuke
 * @date 2021/11/8 11:41
 * 自定义工具类
 *      获取连接对象
 *      获取数据源:DataSource
 */
public class DruidJbdcUtils {
    //线程 存储Connection:模拟线程
    private static ThreadLocal<Connection> t1 = new ThreadLocal<>() ;
    private static DataSource ds ;

    //静态代码块
    static{
        try {
            //加载druid.properties配置文件
            Properties prop = new Properties() ;
            //读取当前druid.properties里面的内容,获取到它所在的资源文件输入流对象
            InputStream inputStream = DruidJbdcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
            //加载属性列表中
            prop.load(inputStream) ;
            //创建数据源对象
             ds = DruidDataSourceFactory.createDataSource(prop); //获取数据源
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    //定义静态功能,获取数据源
    public static DataSource getDataSource(){
        return ds ;
    }

    //获取连接对象
    //连接对象现在模拟线程:每一个用户都要连接对象,将连接对象:存储ThreadLocal
    public static Connection getConnetion(){
        Connection conn = null ;
        //先从线程ThreadLocal获取当前里面的连接对象
        //get():获取当前线程所在的连接对象
        try {
            conn = t1.get();
            if(conn == null ){
                //如果当前线程没有没有连接对象
                //从数据库连接池中获取
                 conn = ds.getConnection(); //从数据源(连接池)中获取连接对象,将连接对象绑定当当前线程上
                //绑定当前当线程上
                t1.set(conn);

            }
            return  conn ;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return  null ;
    }


    //封装释放资源代码
    //针对DQL语句操作,释放资源
    //ResuletSet,Statement,Connection
    public static void close(ResultSet rs, Statement stmt, Connection conn){

        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(stmt!=null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }


    // 将释放资源也可以封装到功能中
    //针对的是DDL/DML语句操作时释放资源
    public static void close(Statement stmt,Connection conn){
        close(null,stmt,conn);
    }

    //后期需要用到事务
    //封装事务的代码
    //开启事务
    public static void startStransaction() throws SQLException {
        Connection connection = ds.getConnection();
        connection.setAutoCommit(false) ; //禁用自动提交
        //释放资源
        connection.close() ; //归还到连接池中
        //需要从线程中解绑
        t1.remove();
    }

    //事务回滚
    public static void rollBackAndClose() throws SQLException {
        Connection connection = ds.getConnection();
        connection.rollback() ;//事务回滚
        //释放资源
        connection.close() ; //归还到连接池中
        //需要从线程中解绑
        t1.remove();
    }

    //提交事务
    public static void commitAndClose() throws SQLException {
        Connection connection = ds.getConnection();
        connection.commit(); ;//提交事务
        //释放资源
        connection.close() ; //归还到连接池中
        //需要从线程中解绑
        t1.remove();
    }

    public static void main(String[] args) {
        DataSource dataSource = DruidJbdcUtils.getDataSource();
        System.out.println(dataSource);
        Connection connetion = DruidJbdcUtils.getConnetion();
        System.out.println(connetion);
    }


}
